#include <dlfcn.h>
#include <fstream>
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include "wrk_config_loader.h"
#include <sstream>
#include "wrk_logger.h"
#include <math.h>
#include <limits.h>
#include <string.h>


using namespace std;
WrkConfigLoader::WrkConfigLoader(const std::string &filepath)
{
    string text_line;
	ifstream m_file(filepath.c_str(),ios::in);
	if(!m_file){
		CDEBUG<<"open "<<filepath<<" fail!"<<endl;
		return ;
	}

	this->filepath = filepath;
	
	string seg;
	while(getline(m_file, text_line)){	
		text_line = trim(text_line);

		if(text_line.empty()){
			continue ;
		}

		if((text_line.find_first_of('#',0))!= string::npos){
			continue ;
		}

		int pos_left	= 0;
		int pos_right	= 0;		
		if((pos_left=text_line.find_first_of('[',0))!=string::npos &&
			(pos_right=text_line.find_first_of(']',0))!=string::npos){
			seg = trim(text_line.substr(pos_left+1, pos_right-1));

			continue ;
		}

        parser_seg(seg, text_line);
	}
};

WrkConfigLoader::~WrkConfigLoader()
{

};

void WrkConfigLoader::parser_seg(const std::string &seg_name, const std::string &line)
{

    int pos = 0;
	if((pos = line.find_first_of('=',0))!=string::npos){
		string k = trim(line.substr(0,pos));
		string v = trim(line.substr(pos+1,line.length()-pos-1));
        if(!map_seg[seg_name].count(k)){
			map_seg[seg_name][k] = v;
		}
	}
}

const std::string WrkConfigLoader::get_conf_realpath()
{
	char resolved_path[128];
	char *ret = realpath(this->filepath.c_str(), resolved_path);
	if(ret==NULL) {
		cout << "WrkConfigLoader::get_conf_realpath Failure: " << strerror(errno) <<endl;
		exit(-1);
	}

	return string(resolved_path);
}

std::string WrkConfigLoader::get_string_value(const std::string &seg_name, const std::string &key)
{
	std::stringstream ss;
	if(map_seg[seg_name].count(key)==0) {
		ss << "WrkConfigLoader::get_string_value error! have no "<<key <<" in segment "<<seg_name;
		throw ss.str();
	}

	return map_seg[seg_name][key];
}

int WrkConfigLoader::get_int_value(const std::string &seg_name, const std::string &key) 
{
	std::stringstream ss;
	if(map_seg[seg_name].count(key)==0) {
		ss << "WrkConfigLoader::get_int_value error! have no "<<key <<" in segment "<<seg_name;
		throw ss.str();
	}

	int ret;

	std::string value = map_seg[seg_name][key];

	ss << value;
	ss >> ret;

	return ret;
}

long WrkConfigLoader::get_long_value(const std::string &seg_name, const std::string &key)
{
	std::stringstream ss;
	if(map_seg[seg_name].count(key)==0) {
		ss << "WrkConfigLoader::get_long_value error! have no field:"<<key <<" in segment: "<<seg_name;
		throw ss.str();
	}

	long ret;
	std::string value = map_seg[seg_name][key]; 
	ss << value;
	ss >> ret;

	return ret;
}

string WrkConfigLoader::trim(string s)   
{  
    if (s.empty())   
    {  
        return s;  
    }  
  
    s.erase(0,s.find_first_not_of(" "));  
    s.erase(s.find_last_not_of(" ") + 1);  
    return s;  
} 

int WrkConfigLoader::str_cnt(string str,string sub)
{
	int pos = 0;
	int cnt = 0;
	while((pos=str.find_first_of(sub,pos))!=string::npos){
		cnt++;
		++pos;
	}
	
	return cnt;
}


void WrkConfigLoader::debug()
{	
	for(MAP_SEG::iterator it=map_seg.begin();it!=map_seg.end();++it) {
        CDEBUG <<"[" <<it->first << "]" <<endl;
        for(MAP_ITEM::iterator itt = it->second.begin(); itt!=it->second.end(); ++itt) {
            CDEBUG << "     "<<  itt->first << " = " << itt->second <<endl;
        }
    }
}